package com.loong.android.views.adapter;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import java.util.ArrayList;
import java.util.HashMap;

import loong.lang.Array;

/**
 * 列表适配器
 */
public class ListAdapter extends BaseAdapter {

    private Event event;
    private Object extra;

    /**
     * 取附加的数据
     */
    public Object getExtra() {
        return extra;
    }

    /**
     * 设置附加的数据
     * @param extra 附加数据
     */
    public ListAdapter setExtra(Object extra) {
        this.extra = extra;
        return this;
    }

    /**
     * 通过视图id获取视图对象，在第一次获取到项目视图的子视图对象后，会缓存起来，下次获取时直接从缓存中提取，可提高列表的渲染效率。
     * @param view 父视图
     * @param id 视图id
     */
    public static <T extends View> T getViewById(View view, int id) {
        return getHolderView(view, id);
    }

    /**
     * 当列表数据改变时，可以调用本函数刷新列表。本函数只会重新渲染可见的列表项目，而不是整个列表，可以提高渲染效率。
     */
    public void refresh() {
        super.notifyDataSetChanged();
    }

    /**
     * 当列表数据改变时，可以调用本函数刷新列表，与refresh的区别在于本函数是重绘整个列表
     * 使得列表恢复到初始状态
     */
    public void refreshAll() {
        super.notifyDataSetInvalidated();
    }

    /**
     * 取列表项目视图类型总数
     */
    public int getViewTypeCount() {
        return super.getViewTypeCount();
    }

    /**
     * 设置列表渲染的事件
     * @param event 事件
     */
    public void setEvent(Event event) {
        this.event = event;
    }

    @Override
    public int getCount() {
        return event == null ? 0 : event.getItemCount(this);
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return event == null ? null : event.onGetItemView(this, position, convertView, parent);
    }

    /**
     * 列表渲染时的接口事件
     */
    public abstract static class Event {

        /**
         * 列表获取项目的总数，需要通过计算数据数组的成员数量，返回需要显示的项目数量。默认返回0
         */
        public int getItemCount(ListAdapter adapter) {
            return 0;
        }

        /**
         * 当项目载入项目视图时，操作被渲染的项目，根据自己的业务需求将列表项目渲染成想要的样子。
         * 这个事件在列表刷新和滚动过程中有可能触发多次。
         * @param position 项目索引
         * @param itemView 项目视图，当第一次渲染项目视图时，该值为空，需要创建视图对象给列表项目。
         *                 第二次渲染该项目时，一般情况下会返回之前创建的项目视图。但由于列表的缓存机制或者系统回收的原因，
         *                 仍有可能得到为空的项目视图，此时需要重新创建该项目的视图。创建项目视图可以通过
         *                 ViewTools.toView和toView2方法，从布局资源id生成视图对象。
         *                 若需要对项目视图中的子视图进行操作，可以通过{@link #getViewById}静态函数获取子视图对象，
         *                 该函数会在第一次获取到子视图对象后，缓存起来，下次获取时直接从缓存中提取，可提高列表的渲染效率。
         * @param parent 项目的父视图
         * @return 返回一个视图对象，用于渲染当前的列表项目，默认返回null
         */
        public View onGetItemView(ListAdapter adapter, int position, View itemView, ViewGroup parent) {
            return null;
        }
    }

    /**
     * @param view 所有缓存View的根View
     * @param id view的id
     */
    private static <T extends View> T getHolderView(View view, int id) {
        HashMap<Integer, View> viewHolder = null;
        if(view.getTag() == null) {
            viewHolder = new HashMap<>();
            view.setTag(viewHolder);//创建集合和根View关联
        }else  {
            viewHolder = (HashMap<Integer, View>) view.getTag();
        }
        View childView = viewHolder.get(id);
        if (childView == null) viewHolder.put(id, (childView = view.findViewById(id)));
        return (T) childView;
    }
}
